/**
 * MayBe函子
 */
interface MapFunc<T> {
  (value: T | null | undefined): T | null | undefined
}

class MayBe<T> {
  static of <T>(value?: T | null | undefined): MayBe<T> {
    return new MayBe(value)
  }

  private _value: T | null | undefined
  constructor (value: T | null | undefined) {
    this._value = value
  }

  // 是空值时直接返回值为空的新函子，不用fn去做处理，避免出现出错
  map (fn: MapFunc<T>): MayBe<T> | MayBe<null> {
    return this.isNothing() ?  MayBe.of(null) : MayBe.of(fn(this._value))
  }

  // 判断是否是空值
  isNothing (): boolean {
    return this._value === undefined || this._value === null
  }
}

let r1 = MayBe.of<string>('Hello World')
  .map(x => (x as string).toUpperCase())
console.log(r1)

let r2 = MayBe.of<string>()
  .map(x => (x as string).toUpperCase())
console.log(r2)

// MayBe函子不知道在哪一步出现了空值
let r3 = MayBe.of<string>()
  .map(x => (x as string).toUpperCase())
  .map(x => null)
  .map(x => x.split(' '))
console.log(r3)
